#include <stdio.h>
#include <string>
#include "socket.hpp"

#define Size 128
#define defaultFd -1

class Server
{
public:
    Server(uint16_t port)
        : port_(port)
    {
        for (int i = 0; i < Size; i++)
        {
            Filefd[i] = defaultFd;
        }
    }
    ~Server()
    {
    }

public:
    void Init()
    {
        ListenSocket.Socket();
        ListenSocket.Bind(port_);
        ListenSocket.Listen();
    }

    void dispatcher(fd_set &Read, int n)
    {
        for (int i = 0; i < n; i++)
        {
            if (FD_ISSET(ListenSocket.Listenfd(), &Read))
            {
                int fd = ListenSocket.Accept();

                printf("get a line,fd:%d\n", fd);
                // 添加资源等待
                for (int i = 1; i < Size; i++)
                {
                    if (Filefd[i] == defaultFd)
                    {
                        Filefd[i] = fd;
                    }
                }
                FD_CLR(ListenSocket.Listenfd(), &Read);
            }
            else
            {
                std::string buffer;
                // 判断哪个资源就绪
                //  在这里使用read会不会阻塞？
                for (int i = 1; i < Size; i++)
                {
                    if (Filefd[i] != defaultFd)
                    {
                        if (FD_ISSET(Filefd[i], &Read))
                        {
                            while (1)
                            {
                                int n = read(Filefd[i], (char *)buffer.c_str(), buffer.size());

                                if (n > 0)
                                {
                                    printf("get a message,fd:%d# %s\n", Filefd[i], buffer.c_str());
                                }
                                else if (n == 0)
                                {
                                    FD_CLR(Filefd[i], &Read);
                                }
                                else
                                {
                                    if (errno == EAGAIN)
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        lg(Fatal, "READ err,errno:%d,str:%s", errno, strerror(errno));
                                        exit(-1);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    void Start()
    {
        int listenfd = ListenSocket.Listenfd();
        Filefd[0] = listenfd;
        // 为什么不能放在外面
        //  fd_set read;
        //  FD_ZERO(&read);
        //  //timeval timeout{5,0};写在外面只能timeout一次，后面都是0秒就进行一次timeout
        //  //timeval timeout({5,0});不能这样写
        //  FD_SET(listenfd,&read);
        while (1)
        {
            // 为什么fd_set不能放外面？
            // 因为它是输入输出型参数
            fd_set read;
            FD_ZERO(&read);
            // 建立连接就是读取数据，加入读位图
            // FD_SET(listenfd,&read);
            for (int i = 0; i < Size; i++)
            {
                if (Filefd[i] != defaultFd)
                    FD_SET(Filefd[i], &read);
            }

            timeval timeout{5, 0};

            int n = select(listenfd + 1, &read, nullptr, nullptr, &timeout);

            switch (n)
            {
            case 0:
                printf("NOT RESOURE\n");
                break;
            case -1:
                printf("Select Err\n");
                break;
            default:
                // 对资源就绪的文件进行操作
                dispatcher(read, n);
                sleep(1);
            }
        }
    }

private:
    Sock ListenSocket;
    uint16_t port_;
    int Filefd[Size];
};